package com.seed.util;

import cn.hutool.core.util.StrUtil;

import java.util.ArrayList;
import java.util.List;

public class StrKit {

    public static List<String> bracket(String s) {
        return bracket(s,'[',']');
    }

    /**
     * 解析出两个字符之间的字符串
     * @param s: 需要解析的字符串，如：String s = "(_).([a.a].[b].[c])";
     * @param open: 起始字符
     * @param close: 结束字符
     * @return 解释出来的列表
     */
    public static List<String> bracket(String s,char open,char close) {
        List<String> ret = new ArrayList<>();
        if(StrUtil.isBlank(s)) return ret;

        StringBuilder exp = new StringBuilder();
        boolean started = false;
        for(char c: s.toCharArray()) {
            if(!started && c == open) {
                started = true;
            } else if(c == close) {
                if(exp.length()>0) {
                    ret.add(exp.toString());
                    exp = new StringBuilder();
                    started = false;
                }
            } else {
                if(started) exp.append(c);
            }
        }

        return ret;
    }

    public static String sqlPos(Object ...params) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < params.length; i++) {
            if(sb.length() > 0) {
                sb.append(',');
            }

            sb.append('?');
        }

        return sb.toString();
    }

    /**
     * 字符串模糊匹配
     * <p>example:
     * <p> user* user-add   --  true
     * <p> user* art-add    --  false
     * @param patt 表达式
     * @param str 待匹配的字符串
     * @return 是否可以匹配
     */
    public static boolean vagueMatch(String patt, String str) {
        // 两者均为 null 时，直接返回 true
        if(patt == null && str == null) {
            return true;
        }
        // 两者其一为 null 时，直接返回 false
        if(patt == null || str == null) {
            return false;
        }
        // 如果表达式不带有*号，则只需简单equals即可 (这样可以使速度提升200倍左右)
        if( ! patt.contains("*")) {
            return patt.equals(str);
        }
        // 深入匹配
        return vagueMatchMethod(patt, str);
    }

    /**
     * 字符串模糊匹配
     *
     * @param pattern /
     * @param str    /
     * @return /
     */
    public static boolean vagueMatchMethod( String pattern, String str) {
        int m = str.length();
        int n = pattern.length();
        boolean[][] dp = new boolean[m + 1][n + 1];
        dp[0][0] = true;
        for (int i = 1; i <= n; ++i) {
            if (pattern.charAt(i - 1) == '*') {
                dp[0][i] = true;
            } else {
                break;
            }
        }
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (pattern.charAt(j - 1) == '*') {
                    dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
                } else if (str.charAt(i - 1) == pattern.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
            }
        }
        return dp[m][n];
    }

    //类型转换====start
    public static Integer toInt(String s, Integer defval) {
        if(StrUtil.isBlank(s)) return defval;

        return Integer.parseInt(s);
    }

    public static Integer toInt(String s) {
        return toInt(s, null);
    }

    public static Boolean toBool(String s, boolean defval) {
        if(StrUtil.isBlank(s)) return defval;

        List<String> falseVals = List.of("", "null", "NULL", "0", "false", "FALSE", "no", "NO", "f", "F");
        return falseVals.contains(s);
    }

    public static Boolean toBool(String s) {
        return toBool(s, false);
    }

    //类型转换====end


    /**
     * 将字符串截成两段
     * @param s 字符串
     * @param ch 分隔符
     * @param isLast 是否最后一个
     * @return [第一段，第二段]
     */
    public static String[] cutInTwo(String s, char ch, boolean isLast) {
        if(!s.contains(String.valueOf(ch))) return isLast ? new String[]{"", s} : new String[]{s, ""};

        int pos = isLast ? s.lastIndexOf(ch) : s.indexOf(ch);
        return new String[]{s.substring(0, pos), s.substring(pos + 1)};
    }

    /**
     * 将两个字符串拼接
     * @param prefix 第一个字符串
     * @param s 第二个字符串
     * @param ch 拼接符
     * @return 拼接后的字符串
     */
    public static String concat(String prefix, String s, char ch) {
        return StrUtil.isBlank(prefix) ? s : prefix + ch + s;
    }

    public static String concat(String prefix, String s) {
        return concat(prefix, s, '.');
    }

    public static String backquote(String s) {
        return "`" + s + "`";
    }

    /**
     * 拆分条件
     *
     * @param condition countries.nameZh_like=中国
     * @return [countries.nameZh, like, 中国]
     */
    public static String[] splitCondition(String condition) {
        String[] items = StrKit.cutInTwo(condition, '=', false);
        String fieldAndOp = items[0];
        String value = items[1];
        int pos = fieldAndOp.lastIndexOf('_');
        String finalColumn = StrUtil.toUnderlineCase(fieldAndOp.substring(0, pos));
        String op = fieldAndOp.substring(pos + 1);
        return new String[]{finalColumn, op, value};
    }

    public static List<String> toList(String... args) {
        List<String> ret = new ArrayList<>();
        for(String arg: args) {
            if(StrUtil.isBlank(arg)) continue;

//            arg = StrUtil.toUnderlineCase(arg);
            String[] items = arg.split(",");
            for(String item: items) ret.add(item.trim());
        }

        return ret;
    }

    public static String selfTableAlias(String basePath) {
        return StrUtil.isBlank(basePath) ? "t" : StrUtil.toCamelCase(basePath);
    }

    public static String targetTableAlias(String basePath, String cross) {
        String path = concat(basePath, cross);
        return StrUtil.toCamelCase(path);
    }

    public static String throughAlias(String basePath, String cross) {
        return String.format("%s_%s", StrUtil.isBlank(basePath) ? "t" : basePath, cross);
    }

    public static String whereKey(String path, String op, String val) {
        return path + '_' + op + (StrUtil.isBlank(val) ? "" : '=' + val);
    }

    public static String seedName(String fileName) {
        return StrUtil.toCamelCase(cutInTwo(fileName, '.', false)[0].replace('-', '_'));
    }

//    public static String appKey(String owner, String appName) {
//        if(StrUtil.isBlank(appName)) throw new RuntimeException("应用名不能为空");
//
//        return (StrUtil.isBlank(owner) ? "" : owner + '.') + appName;
//    }
//
//    public static String microKey(String owner, String appName, String microName) {
//        String appKey = appKey(owner, appName);
//        if(StrUtil.isBlank(microName)) return appKey;
//
//        return appKey + '.' + microName;
//    }
//
//    public static String microDataSourceKey(String appDataSourceKey, String microName) {
//        return appDataSourceKey + "_m_" + microName;
//    }
//
//    public static String appDataSourceKey(String owner, String appName, String tenantname) {
//        if(StrUtil.isBlank(appName)) throw new RuntimeException("应用名称不能为空");
//
//        StringBuilder sb = new StringBuilder();
//
//        String t = StrUtil.isBlank(tenantname) ? "" : "t_" + tenantname;
//        String o = StrUtil.isBlank(owner) ? "" : "o_" + owner;
//        String a = "a_" + appName;
//
//        if(StrUtil.isNotBlank(t)) sb.append(t);
//        if(StrUtil.isNotBlank(o)) {
//            if(sb.length() > 0) sb.append('_');
//            sb.append(o);
//        }
//
//        if(sb.length() > 0) sb.append('_');
//        sb.append(a);
//
//        return sb.toString();
//    }

    /**
     * appKey: 应用的键
     * app
     * owner.app
     * @param owner: 拥有者
     * @param appName： 应用名
     * @return
     */
    public static String appKey(String owner, String appName) {
        if(StrUtil.isBlank(appName)) throw new RuntimeException("应用名称不能为空");
        return StrUtil.isBlank(owner) ? appName : owner + '.' + appName;
    }

    /**
     * microKey：微服务的键，主应用也是一个微服务
     * app:  主应用
     * app.microName： 微服务
     * owner.app: 主应用(带拥有者)
     * owner.app.microName： 微服务(带拥有者)
     * @param appKey： 应用的键
     * @param microName： 微服务名
     * @return
     */
    public static String microKey(String appKey, String microName) {
        return appKey + (StrUtil.isBlank(microName) ? "" : '.' + microName);
    }

    /**
     * dataSourceKey: 数据源键
     * 默认：开发系统数据源
     * app：内部主应用数据源
     * tenant_app：租户主应用数据源
     * owner.app：内部主应用数据源(带拥有者)
     * owner.tenant_app：租户主应用数据源(带拥有者)
     * app_micro：内部微服务数据源
     * tenant_app_micro：租户微服务数据源
     * owner.app_micro：内部微服务数据源(带拥有者)
     * owner.tenant_app_micro：租户微服务数据源(带拥有者)
     * @param owner 拥有者
     * @param appName 应用名
     * @param tenantname 租户名
     * @param microName 微服务名
     * @return
     */
    public static String dataSourceKey(String owner, String appName, String tenantname, String microName) {
        if(StrUtil.isBlank(appName)) throw new RuntimeException("应用名称不能为空");

//            app：内部主应用数据源
//            tenant_app：租户主应用数据源
//            app_micro：内部微服务数据源
//            tenant_app_micro：租户微服务数据源
//            owner.app：内部主应用数据源(带拥有者)
//            owner.tenant_app：租户主应用数据源(带拥有者)
//            owner.app_micro：内部微服务数据源(带拥有者)
//            owner.tenant_app_micro：租户微服务数据源(带拥有者)
        return (StrUtil.isBlank(owner) ? "" : owner + '.')
                + (StrUtil.isBlank(tenantname) ? "" : tenantname + '_')
                + appName
                + (StrUtil.isBlank(microName) ? "" : '_' + microName);
    }

//    /**
//     * app的键名
//     * app
//     * tenant_app
//     * owner.app
//     * owner.tenant_app
//     * @return
//     */
//    public static String appKey(String owner, String tenantname, String appName) {
//        if(StrUtil.isBlank(appName)) throw new RuntimeException("应用名称不能为空");
//
//        String tmp = StrUtil.isBlank(tenantname) ? appName : tenantname + '_' + appName;
//        return StrUtil.isBlank(owner) ? tmp : owner + '.' + tmp;
//    }

//    /**
//     * 除了app之外的键名
//     * app_micro
//     * tenant_app_micro
//     * owner.app_micro
//     * owner.tenant_app_micro
//     * @param appKey
//     * @param microName
//     * @return
//     */
//    public static String microKey(String appKey, String microName) {
//        return appKey + (StrUtil.isBlank(microName) ? "" : '_' + microName);
//    }

    public static void main(String[] args) {
        String owner = "owner";
        String tenantname = "tenant";
        String appName = "app";
//        System.out.println(appKey(owner, tenantname, appName));
    }
}
